home *** CD-ROM | disk | FTP | other *** search
- ;
- ; VGA support routines for raster oriented graphics
- ;
- ; Quincey Koziol June 1988
- ;
- ; National Center for Supercomputing Applications, University of Illinois
- ; 153 Water Resources Building
- ; 605 E. Springfield Ave.
- ; Champaign, Ill 61820
- ; (217)244-0072
- ;
- TITLE VGA GRAPHICS SUPPORT
- INCLUDE DOS.MAC
- SETX
- PSEG
- PUBLIC PUTMAPV,GETMAP,VGALINE1,VGAPT,VGAMODE,VGAOFF,VGAON,VGASCRN
- PUBLIC SHOWPALV,NOPALV,SCRLRITE,SCRLLEFT,SCRLUP,SCRLDOWN,OUTLINEV,BALL
- ;
- ; take three arrays of color tables and interleave them into the
- ; VGA registers in the fashion Red, Green, Blue.
- ;
-
- PUTMAPV PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
- ;
- MOV AX,[BP+X+2]
- MOV DS,AX ; WHERE TO GET MAPS (SEG)
- MOV SI,[BP+X] ; WHERE TO GET RED
- MOV DI,[BP+X+4] ; WHERE TO GET GREEN
- MOV BP,[BP+X+8] ; WHERE TO GET BLUE
- MOV DX,03C8H ; I/O PORT FOR PEL TABLE
- MOV AL,0 ; VALUE FOR BEGINNING OF TABLE
- OUT DX,AL ; START OUTPUTTING VALUES
- INC DX ; INCREMENT DX TO OUTPUT TABLE
- MOV CX,256 ; LENGTH OF THE TABLE IN BYTE TRIPLES
-
- DORGB:
- MOV AL,DS:[SI] ; GET A RED BYTE
- SHR AL,1
- SHR AL,1 ; GET RID OF TWO HIGHEST BITS
- OUT DX,AL
- INC SI
- ;
- MOV AL,DS:[DI] ; GET A GREEN BYTE
- SHR AL,1
- SHR AL,1 ; GET RID OF TWO HIGHEST BITS
- OUT DX,AL
- INC DI
- ;
- MOV AL,DS:[BP] ; GET A BLUE BYTE
- SHR AL,1
- SHR AL,1 ; GET RID OF TWO HIGHEST BITS
- OUT DX,AL
- INC BP
- ;
- LOOP DORGB ; CONTINUE PRINTING UNTIL ALL 768 BYTES ARE WRITTEN
- ;
- POP ES
- POP DS
- POP BP
- RET
-
- PUTMAPV ENDP
-
- GETMAP PROC FAR
- RET
- GETMAP ENDP
-
- ;
- ; Transfer line to vga screen
- ;
- ; usage : vgaline1(x,y,buf,xoff,linelen)
- ;
- VGALINE1 PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- OKBANK:
- MOV AX,0A000H ; DATA BUFFER
- MOV ES,AX
- MOV SI,[BP+X+4] ; WHERE DATA WILL COME FROM
- MOV AX,[BP+X+8] ; GET THE X OFFSET INTO THE ARRAY
- CMP AX,0 ; CHECK FOR NEGATIVE OFFSET
- JGE OKSIGN ; JUMP AROUND FIXING THE WINDOW
- NEG AX ; TAKE THE OPPOSITE VALUE
- ADD AX,[BP+X] ; AND ADD IT TO THE POSITION ON THE SCREEN
- MOV [BP+X],AX ; AND RE-STORE THE POSITION
- MOV AX,[BP+X+8] ; GET THE NEGATIVE OFFSET AGAIN
- ADD AX,[BP+X+10] ; REDUCE THE NUMBER OF BYTES TO COPY TO THE SCREEN
- MOV [BP+X+10],AX ; AND STORE THE NUMBER OF BYTES AGAIN
- OKSIGN:
- ADD SI,AX ; ADD THE OFFSET TO THE OFFSET OF THE ARRAY
- ;
- MOV AX,[BP+X+6] ; SEGMENT OF DATA
- MOV DS,AX
- ;
- MOV AX,[BP+X+2] ; GET Y VALUE AGAIN
- MOV DX,320 ; GET LENGTH OF A LINE
- MUL DX
- JA DONTFIX ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
- MOV BX,ES ; GET THE ES
- ADD BX,DX ; INCREMENT THE ES
- MOV ES,BX ; AND REPLACE IT
- DONTFIX:
- ADD AX,[BP+X] ; X VALUE OF WHERE ON SCREEN ADDED IN
- MOV DI,AX ; PREPARE FOR MOVS
- MOV CX,[BP+X+10] ; HOW MANY BYTES?
- BLAST:
- REP MOVSB
-
- POP ES
- POP DS
- POP BP
- RET
- VGALINE1 ENDP
-
- ; point on vga screen
- ;
- ; usage : vgapt(x,y,color)
- ;
- VGAPT PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- ;
- ; READY TO PUT THE POINT
- ;
- POKBANK:
- MOV AX,0A000H ; DATA BUFFER
- MOV ES,AX
-
- MOV AX,[BP+X+2] ; GET Y VALUE AGAIN
- MOV DX,320
- MUL DX
- ADD AX,[BP+X] ; X VALUE OF WHERE ON SCREEN ADDED IN
-
- MOV DI,AX ; PREPARE FOR MOVS
- MOV AL,[BP+X+4] ; GET COLOR TO PUT THERE
-
- STOSB ; PUT IT
-
- POP ES
- POP DS
- POP BP
- RET
- VGAPT ENDP
-
- VGAMODE PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,[BP+X] ;GET SCREEN MODE TO SWITCH TO
- MOV AH,00H ;ENTER VIDEO_IO ROUTINE (SET MODE=0)
- INT 10H ;VIDEO INTERUPT
-
- POP ES
- POP DS
- POP BP
- RET
- VGAMODE ENDP
-
-
- VGAOFF PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV DX,03C4H ;ADDRESS OF THE SEQ CONTROLLER
- MOV AL,01H ;INDEX OF THE CLOCKING MODE REGISTER
- OUT DX,AL ;SET UP TO READ THE CLOCKING MODE REGISTER
- MOV DX,03C5H ;ADDRESS TO READ FROM
- IN AL,DX ;GET THE CLOCKING MODE REGISTER
- OR AL,20H ;MASK OFF THE SCREEN ENABLE BIT
- MOV BL,AL ;KEEP THAT AROUND
- MOV DX,03C4H ;ADDRESS OF THE SEQ CONTROLLER
- MOV AL,01H ;INDEX OF THE CLOCKING REGISTER
- OUT DX,AL ;SET UP TO WRITE BACK THE CLOCKING MODE REGISTER
- INC DX ;SET TO ADDRESS TO WRITE TO
- MOV AL,BL ;GET BACK THE PROPER VALUE
- OUT DX,AL ;TURNS OFF THE VGA SCREEN
-
- POP ES
- POP DS
- POP BP
- RET
- VGAOFF ENDP
-
- VGAON PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV DX,03C4H ;ADDRESS OF THE SEQ CONTROLLER
- MOV AL,01H ;INDEX OF THE CLOCKING MODE REGISTER
- OUT DX,AL ;SET UP TO READ THE CLOCKING MODE REGISTER
- INC DX ;ADDRESS TO READ FROM
- IN AL,DX ;GET THE CLOCKING MODE REGISTER
- AND AL,0DFH ;TURN ON THE SCREEN ENABLE BIT
- MOV BL,AL ;KEEP THAT AROUND
- MOV DX,03C4H ;ADDRESS OF THE SEQ CONTROLLER
- MOV AL,01H ;INDEX OF THE CLOCKING REGISTER
- OUT DX,AL ;SET UP TO WRITE BACK THE CLOCKING MODE REGISTER
- INC DX ;SET TO ADDRESS TO WRITE TO
- MOV AL,BL ;GET BACK THE PROPER VALUE
- OUT DX,AL ;TURNS ON THE VGA SCREEN
-
- POP ES
- POP DS
- POP BP
- RET
- VGAON ENDP
-
- X_COL DW 0
- Y_ROW DW 0
- TEMP1 DB 0
- TEMP2 DW 0
- TEMP3 DW 0
- TEMP4 DW 0
- TEMP5 DW 0
- NUM_CHARS DB 0
- CRT_ADDR DW 03D4H
- ATTR_ADDR DW 03C0H
- SEQ_ADDR DW 03C4H
- GRAF_ADDR DW 03CEH
- ATTR_TABLE LABEL BYTE
- DB 41H ;BYTE 10H OF THE TABLE!!!
- DB 0 ;BORDER COLOR OF SCREEN BYTE 11H OF TABLE
- DB 0FH ;BYTE 12H OF ATTR. TABLE
- DB 0 ;AMOUNT TO SHIFT SCREEN TO LEFT BY, BYTE 13H OF TABLE
- DB 0 ;NO COLOR SELECTION NECESSARY, BYTE 14H OF TABLE
- SEQ_TABLE LABEL BYTE
- DB 3 ;DON'T RESET THE SYSTEM (0'S WOULD RESET)
- DB 1 ;A WHOLE BUNCH OF THINGS, BYTE 01H OF TABLE
- DB 0FH ;ALLOW WRITES TO ALL MEMORY MAPS
- DB 0 ;DON'T WORRY ABOUT THE CHARACTER MAPS
- DB 0EH ;SET UP FOR EXTENDED MEMORY
- GRAF_TABLE LABEL BYTE
- DB 0 ;WRITE A BLANK SCREEN FOR SET/RESETS
- DB 0 ;ENABLE THE SET/RESET FUNCTION
- DB 0 ;COLOR COMPARE VALUE IS ZERO
- DB 0 ;JUST WRITE TO MEMORY, DONT ROTATE, DONT AND or OR
- DB 0 ;SELECT MAP ZERO TO READ FROM
- DB 40H ;SELECT 256 COLOR MODE AMONG OTHER THINGS
- DB 5 ;SELECT 128K MODE AT A0000H AND GRAPHICS MODE
- DB 0FH ;DON'T PARTICIPATE IN THE COLOR COMPARE CYCLE
- DB 0FFH ;ALLOW ALL BITS TO BE WRITTEN TO
- TABLE LABEL BYTE
- DB 5FH ;0 ;HORIZONTAL TOTAL=# OF CHARS+# OF CHARS*.25-5
- DB 4FH ;0 ;HORIZONTAL DISPLAY ENABLE END=# OF CHARS-1
- DB 50H ;0 ;START HORIZONTAL BLANKING=# OF CHARS
- DB 82H ;0 ;END HORIZONTAL BLANKING
- ; BITS
- ; 7 = 1
- ; 6,5 = 0,0
- ; 4-0 = LOW 5 BITS OF AN EIGHT BIT # = TABLE(00)+3
- DB 54H ;0 ;START HORIZONTAL RETRACE PULSE=(TABLE(00)+TABLE(02)/2
- DB 80H ;0 ;END HORIZONTAL RETRACE
- ; BITS
- ; 7 = SIXTH BIT OF TABLE(00)+3
- ; 6,5 = 0,0
- ; 4-0 = 0
- DB 0BH ;0 ;VERTICAL TOTAL=LOW EIGHT BITS OF
- ; IF Y_ROW<=200 THEN Y_ROW*2.5-2
- ; IF Y_ROW>200 THEN Y_ROW*1.25-2
- DB 3EH ;0 ;OVERFLOW
- ; BITS
- ; 7,6 = 0,0
- ; 5 = BIT 9 OF TABLE(06)
- ; 4 = 1 - BIT 8 OF TABLE(18)
- ; 3 = BIT 8 OF TABLE(15)
- ; 2 = BIT 8 OF TABLE(10)
- ; 1 = BIT 8 OF TABLE(12)
- ; 0 = BIT 8 OF TABLE(06)
- DB 0 ;PRESET ROW SCAN=00
- DB 40H ;0 ;MAXIMUN SCAN LINE
- ; BITS
- ; 7 = 1 IF Y_ROW <=200
- ; 0 IF Y_ROW >200
- ; 6 = 1 - BIT 9 OF TABLE(18)
- ; 5 = BIT 9 OF TABLE(15)
- ; 4-0 = MAX SCAN LINE = 00
- DB 0 ;CURSOR START=00
- DB 0 ;CURSOR END=00
- DB 0 ;START ADDRESS HIGH=00
- DB 0 ;START ADDR LOW=00
- DB 0 ;CURSOR LOCATION HIGH=00
- DB 0 ;CURSOR LOCATION LOW=00
- DB 0EAH ;0 ;VERTICAL RETRACE START=
- ; IF Y_ROW<=200 THEN Y_ROW*2+12
- ; IF Y_ROW>200 THEN Y_ROW+10
- DB 8CH ;0 ;VERTICAL RETRACE END
- ; BITS
- ; 7 = 1 - PROTECT CRTC TABLE REGS 0-7
- ; 0 - DON'T PROTECT REGS 0-7
- ; 6-4 = 0
- ; 3-0 = LOW FOUR BITS OF TABLE(10)+2
- DB 0DFH ;0 ;VERTICAL DISPLAY ENABLE END= LOW EIGHT BITS OF
- ; IF Y_ROW<=200 THEN Y_ROW*2-1
- ; IF Y_ROW >200 THEN Y_ROW-1
- DB 28H ;0 ;OFFSET=# OF CHARS*.5
- DB 0 ;40H ;UNDERLINE LOCATION
- ; BITS
- ; 7 = 0
- ; 6 = 1
- ; 5-0 = 0
- DB 0E7H ;0 ;START VERTICAL BLANK= LOW EIGHT BITS OF
- ; IF Y_ROW<=200 THEN Y_ROW*2+6
- ; IF Y_ROW >200 THEN Y_ROW+6
- DB 04 ;0 ;END VERTICAL BLANK=TABLE(15)+32
- DB 0A3H ;0A3H ;CRTC MODE CONTROL
- ; BITS
- ; 7 = 1
- ; 6 = 0
- ; 5 = 1
- ; 4-2 = 0
- ; 1-0 = 1
- DB 45H ;LINE COMPARE=0345H
-
-
-
- VGASCRN PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- JMP DO_IT ;ABORTING LOADING THE CRTC REGISTERS
-
- MOV AX,[BP+X] ;GET SCREEN X WIDTH (IN PIXELS)
- MOV X_COL,AX ;SAVE SCREEN WIDTH
- MOV CL,3
- SHR AX,CL ;CONVERT # OF COLUMNS INTO NUMBER OF CHARACTERS
- MOV NUM_CHARS,AL ;SAVE # OF CHARS WIDE THE SCREEN IS
- MOV AX,[BP+X+2] ;GET SCREEN HEIGHT (IN PIXELS)
- MOV Y_ROW,AX ;SAVE SCREEN HEIGHT
-
- ;
- MOV SI,0 ;INITIAL VALUE FOR OFFSET INTO TABLE
- MOV AL,TABLE[11H] ;GET PROTECTION BIT
- AND AL,07FH ;MASK OFF TOP BIT
- MOV TABLE[11H],AL ;STORE IT BACK TO ALLOW WRITES TO REGS 0-7
- ;
- MOV DL,NUM_CHARS ;GET NUMBER OF CHARACTERS
- MOV AL,DL
- SHR AL,1
- SHR AL,1 ;GET THE NUMBER OF CHARS DIVIDED BY 4
- ADD AL,DL
- SUB AL,5 ;FINAL VALUE FOR TABLE(00)
- MOV TABLE[SI],AL ;STORE IN FIRST POSION OF TABLE
- INC SI ;INCREMENT FOR NEXT VALUE OF TABLE
- ;
- MOV AL,NUM_CHARS ;GET THE NUMBER OF CHARACTERS
- SUB AL,1 ;MAKE INTO PROPER VALUE
- MOV TABLE[SI],AL ;STORE IN TABLE(01)
- INC SI ;INCREMENT TO NEXT VALUE OF TABLE
- ;
- MOV AL,NUM_CHARS ;GET THE NUMBER OF CHARACTERS WIDE THE SCREEN IS
- MOV TABLE[SI],AL ;STORE TABLE(02)
- INC SI ;INCREMENT TO NEXT VALUE OF TABLE
- ;
- MOV AL,TABLE[00] ;GET TABLE(00)
- ADD AL,3 ;AX HAS TABLE(00)+3 IN IT
- MOV TEMP1,AL ;KEEP TRACK OF THIS NUMBER FOR LATER
- AND AL,1FH ;MASK OFF ALL BUT FIVE LOWEST BITS
- OR AL,080H ;TURN ON THE HIGHEST BIT
- MOV TABLE[SI],AL ;STORE IN TABLE(03)
- INC SI ;GO ON TO NEXT TABLE VALUE
- ;
- MOV AL,TABLE[00] ;GET TABLE(00)
- ADD AL,TABLE[2] ;ADD IN TABLE(02)
- SHR AL,1 ;DIVIDE BY 2
- MOV TABLE[SI],AL ;STORE IN TABLE(04)
- INC SI ;GO ON TO NEXT TABLE VALUE
- ;
- MOV AL,TEMP1 ;GET THE TEMPORARY VALUE SAVED
- SHL AL,1
- SHL AL,1 ;MOVE THE SIXTH BIT INTO THE EIGHT BIT'S POSITION
- AND AL,080H ;CLEAR OUT ALL BUT THE HIGHEST BIT
- MOV TABLE[SI],AL ;STORE IN TABLE(05)
- INC SI ;INCREMENT TABLE INDEX
- ;
- MOV AX,Y_ROW ;GET THE NUMBER OF ROWS ON THE SCREEN
- SHL AX,1 ;MULTIPLY BY 2
- MOV DX,AX ;SAVE THIS VALUE
- MOV AX,Y_ROW ;GET THE NUMBER OF ROWS AGAIN
- SHR AX,1 ;DIVIDE BY 2
- ADD AX,DX ;GET THE TOTAL
- CMP Y_ROW,200 ;CHECK FOR MORE THAN 200 ROWS
- JNA S1 ;IF <=200 ROWS THEN DON'T DIVIDE #
- SHR AX,1 ;DIVIDE NUMBER BY 2
- S1:
- SUB AX,2 ;SUBTRACT 2 FROM TOTAL
- MOV TEMP2,AX ;KEEP AROUND FOR LATER
- MOV TABLE[SI],AL ;STORE LOW EIGHT BITS IN TABLE(06)
- INC SI ;INCREMENT TABLE INDEX
- ;
- INC SI ;COME BACK FOR TABLE(07) LATER AFTER OTHER VALUES ARE CALCULATED
- ;
- INC SI ;TABLE(08) ALWAYS HAS A ZERO IN IT
- ;
- INC SI ;COME BACK FOR TABLE(09) ALSO
- ;
- ADD SI,6 ;NEXT TABLE(0A)-TABLE(0F) ALWAYS HAVE ZEROES IN THEM
- ;
- MOV AX,Y_ROW ;GET THE NUMBER OF ROWS ON THE SCREEN
- CMP AX,200 ;CHECK IF UNDER 200 ROWS
- JA S2 ;YES, MORE THAN 200 LINES SO DON'T MULTIPLY
- SHL AX,1 ;MULTIPLY NUMBER BY 2
- S2:
- ADD AX,10 ;FINAL 9 BIT VALUE
- MOV TEMP3,AX ;KEEP IT AROUND
- MOV TABLE[SI],AL ;STORE THE LOW EIGHT BITS IN TABLE(10)
- INC SI ;INCREMENT TO NEXT TABLE VALUE
- ;
- MOV AL,TABLE[10H] ;GET TABLE(10)
- AND AL,0FH ;MASK OFF TOP FOUR BITS
- MOV TABLE[SI],AL ;STORE IN TABLE(11)
- INC SI ;INCRMENT TABLE INDEX
- ;
- MOV AX,Y_ROW ;GET THE NUMBER OF ROWS
- CMP AX,200 ;CHECK FOR UNDER 200 AGAIN
- JA S3 ;IF OVER 200 THEN DON'T MULTIPLY
- SHL AX,1 ;MULTIPLY BY 2
- S3:
- SUB AX,1 ;FINAL 10 BIT VALUE
- MOV TEMP4,AX ;KEEP THIS AROUND
- MOV TABLE[SI],AL ;STORE IN TABLE(12)
- INC SI ;INCREMENT TABLE INDEX
- ;
- MOV AL,NUM_CHARS ;GET THE NUMBER OF CHARACTERS WIDE
- SHR AL,1 ;DIVIDE IT BY 2
- MOV TABLE[SI],AL ;STORE IN TABLE(13)
- INC SI ;INCREMENT TABLE INDEX
- ;
- INC SI ;TABLE(14) IS PRESET
- ;
- MOV AX,Y_ROW ;GET NUMBER OF ROWS
- CMP AX,200 ;CHECK IF IT IS OVER 200
- JA S4 ;IF OVER 200 THEN DON'T MULTIPLY
- SHL AX,1 ;MULTIPLY BY 2
- S4:
- ADD AX,6 ;FINAL VALUE FOR TEN BIT NUMBER
- MOV TEMP5,AX ;KEEP THIS AROUND
- MOV TABLE[SI],AL ;STORE IN TABLE(15)
- INC SI ;INCREMENT TABLE INDEX
- ;
- MOV AL,TABLE[15H] ;GET TABLE(15)
- ADD AL,32 ;FINAL VALUE FOR TABLE(16)
- MOV TABLE[SI],AL ;STORE IN TABLE(16)
- INC SI ;INCREMENT TABLE INDEX
- ;
- ; TABLE(17) AND TABLE(18) ARE PRESET ALSO
- ;
- ;MAKE TABLE(07)
- MOV AX,TEMP2 ;GET TEN BIT VERSION OF TABLE(06)
- MOV CL,4
- SHR AX,CL ;SHIFT INTO PROPER BIT POSITION (5)
- AND AL,20H ;CLEAR OUT LOWER BITS
- MOV DL,AL ;STORE IT SOMEWHERE
- OR DL,10H ;MESH THE VALUES TOGETHER
- MOV AX,TEMP5 ;GET THE TEN BIT VERSION OF TABLE(15)
- MOV CL,5
- SHR AX,CL ;SHIFT INTO PROPER BIT POSITION (3)
- AND AL,8 ;KILL OFF OTHER BITS
- OR DL,AL ;MESH TOGETHER
- MOV AX,TEMP3 ;GET THE NINE BIT VERSION OF TABLE(10)
- MOV CL,6
- SHR AX,CL ;SHIFT INTO PROPER BIT POSITION (2)
- AND AL,4 ;KILL OTHER BITS
- OR DL,AL ;MESH INTO TOTAL
- MOV AX,TEMP4 ;GET THE TEN BIT VERSION OF TABLE(12)
- MOV CL,7
- SHR AX,CL ;SHIFT INTO PROPER BIT POSITION (1)
- AND AL,2 ;KILL OTHER BITS
- OR DL,AL ;MESH INTO FINAL VALUE
- MOV AX,TEMP2 ;GET THE TEN BIT VERSION OF TABLE(06)
- MOV AL,AH ;GET INTO PROPER BIT POSITION (0)
- AND AL,1 ;KILL OFF OTHER BITS
- OR AL,DL ;RETRIEVE TOTAL VALUE
- MOV TABLE[7],AL ;STORE THIS MISH-MASH INTO TABLE(07)
- ;
- ;MAKE TABLE(09)
- MOV AL,40H ;SET THE VALUE OF TABLE(09) TO BE MODIFIED
- CMP Y_ROW,200 ;CHECK IF MORE THAN 200 ROWS
- JA S5 ;IF IT IS LESS THAN 200 THEN SET BIT (7)
- OR AL,080H ;SET BIT (7)
- S5:
- MOV DL,AL ;KEEP TRACK OF THIS
- MOV AX,TEMP5 ;GET THE TEN BIT VERSION OF TABLE(15)
- MOV CL,4
- SHR AX,CL ;SHIFT BIT 9 INTO BIT 5 POSITION
- AND AL,20H ;KILL OFF OTHER BITS
- OR AL,DL ;GET OTHER STUFF STORED
- MOV TABLE[9],AL ;STORE TABLE(09)
- ;
- MOV AL,TABLE[11H] ;GET TABLE(11)
- OR AL,080H ;SET THE PROTECT BIT AGAIN
- MOV TABLE[11H],AL ;PUT TABLE(11) BACK
-
- DO_IT:
- MOV DX,CRT_ADDR ;GET THE ADDRESS OF THE CRTC CONTROLLER
- MOV CX,019H ;GET THE SIZE OF THE TABLE
- MOV SI,0 ;SET INDEX TO 0
- MOV AX,0 ;CLEAR OUT ACCUMULATOR
- LOOPTOP:
- MOV AL,AH ;INIT LOOP
- OUT DX,AL ;SET CRTC REGISTER NUMBER
- INC DX
- INC AH
- MOV AL,TABLE[SI] ;GET OUTPUT VALUE
- OUT DX,AL ;OUTPUT VALUE TO CRTC REGISTER
- INC SI ;INCREMENT CRTC REGISTER INDEX
- DEC DX ;GO BACK TO CONTROLLER ADDRESS
- LOOP LOOPTOP ;KEEP DOING THIS FOR ALL VALUES
-
- JMP NOPE
-
- CMP X_COL,360 ;CHECK TO SEE IF THE NUMBER OF COLUMNS IS SMALL
- JA NOPE ;THE NUMBER OF COLUMNS IS BIG ENOUGH NOT TO SET BIT
- MOV AL,SEQ_TABLE[1] ;GET THE BYTE TO SET
- OR AL,08H ;TURN ON THE BIT FOR A SMALLISH SCREEN
- MOV SEQ_TABLE[1],AL ;REPLACE THE BYTE
- NOPE:
- MOV DX,SEQ_ADDR ;GET THE ADDRESS OF THE SEQ CONTROLLER
- MOV CX,5 ;GET THE SIZE OF THE TABLE
- MOV SI,0 ;SET THE INDEX TO ZERO
- XOR AX,AX ;CLEAR THE ACCUMULATOR
- SEQ_LOOP:
- MOV AL,AH ;INIT LOOP
- OUT DX,AL ;SET SEQ REGISTER NUMBER
- INC DX
- INC AH
- MOV AL,SEQ_TABLE[SI] ;GET OUTPUT VALUE
- OUT DX,AL ;OUTPUT VALUE TO SEQ REGISTER
- INC SI ;INCREMENT SEQ REGISTER INDEX
- DEC DX ;GO BACK TO CONTROLLER ADDRESS
- LOOP SEQ_LOOP ;KEEP DOING THIS FOR ALL VALUES
-
- MOV DX,GRAF_ADDR ;GET THE ADDRESS OF THE GRAF CONTROLLER
- MOV CX,9 ;GET THE SIZE OF THE TABLE
- MOV SI,0 ;SET THE INDEX TO ZERO
- XOR AX,AX ;CLEAR THE ACCUMULATOR
- GRAF_LOOP:
- MOV AL,AH ;INIT LOOP
- OUT DX,AL ;SET GRAF REGISTER NUMBER
- INC DX
- INC AH
- MOV AL,GRAF_TABLE[SI] ;GET OUTPUT VALUE
- OUT DX,AL ;OUTPUT VALUE TO GRAF REGISTER
- INC SI ;INCREMENT GRAF REGISTER INDEX
- DEC DX ;GO BACK TO CONTROLLER ADDRESS
- LOOP GRAF_LOOP ;KEEP DOING THIS FOR ALL VALUES
-
- MOV DX,ATTR_ADDR ;GET THE ADDRESS OF THE ATTR CONTROLLER
- MOV CX,5 ;GET THE SIZE OF THE TABLE
- MOV SI,0 ;SET THE INDEX TO ZERO
- MOV AX,3000H ;SET THE ACCUMULATOR
- MOV DX,03DAH ;
- IN AL,DX ;SMALL ROUTINE TO SET UP THE ATTR REGISTERS CORRECTLY
- MOV DX,ATTR_ADDR ;
- ATTR_LOOP: ;NOTE THE CONTROLLER AND DATA REGISTERS USE THE SAME I/O PORT
- MOV AL,AH ;INIT LOOP
- OUT DX,AL ;SET ATTR REGISTER NUMBER
- INC AH
- MOV AL,ATTR_TABLE[SI] ;GET OUTPUT VALUE
- OUT DX,AL ;OUTPUT VALUE TO ATTR REGISTER
- INC SI ;INCREMENT ATTR REGISTER INDEX
- LOOP ATTR_LOOP ;KEEP DOING THIS FOR ALL VALUES
-
- MOV DX,03C2H ;ADDRESS OF THE MISC OUTPUT REGISTER
- ; CMP Y_ROW,350 ;CHECK IF ROWS = 350
- ; JNE N1 ;JUMP TO NEXT CHECK
- ; MOV AL,40H ;SET THE VERTICAL AND HORIZONTAL SYNC POLARITY
- ; JMP GO_ON ;JUMP TO FINISH SETTING THE BITS
- ;N1:
- ; CMP Y_ROW,480 ;CHECK IF ROWS = 480
- ; JNE N2 ;JUMP TO SET THE DEFAULT BITS
- ; MOV AL,0C0H ;SET THE VERTICAL AND HORIZONTAL SYNC POLARITY
- ; JMP GO_ON ;JUMP TO FINISH SETTING THE BITS
- ;N2:
- ; MOV AL,080H ;DEFAULT SETTING FOR VERT AND HORI SYNC BITS
- ;GO_ON:
- ; OR AL,23H ;SET THE REST OF THE BITS WE NEED
- MOV AL,63H
- OUT DX,AL ;AND WRITE OUT TO THE MISC OUTPUT REGISTER
-
- MOV DX,03C3H ;ADDRESS OF THE VGA ENABLE REGISTER
- MOV AL,1 ;ENABLE THE VIDEO STUFF
- OUT DX,AL ;WRITE TO THE VGA ENABLE REGISTER
-
- POP ES
- POP DS
- POP BP
- RET
- VGASCRN ENDP
-
- ;
- ; showpalv(&palstore,pal_xoff,pal_yoff);
- ;
- SHOWPALV PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
-
- MOV AX,[BP+X] ;GET OFFSET OF ARRAY
- MOV DI,AX
- MOV AX,[BP+X+2] ;GET SEGMENT OF STORAGE ARRAY
- MOV ES,AX
-
- MOV AX,[BP+X+6] ;GET LINE TO START PALETTE ON
- MOV DX,320 ;GET THE LINE LENGTH
- MUL DX ;GET THE OFFSET INTO THE SCREEN
- ADD AX,[BP+X+4] ;ADD IN THE X OFFSET
- JNC NO_ROLLOVER ;ADDITION DIDN'T CARRY
- INC DX ;INCREMENT THE DX REGISTER ON A CARRY
- NO_ROLLOVER:
- MOV SI,AX ;KEEP TRACK OF THE OFFSET
- MOV BX,SI ;IN TWO PLACES
- MOV AX,320 ;GET THE LINE LENGTH
- MOV DX,8 ;GET THE NUMBER OF LINES
- MUL DX ;GET THE NUMBER OF BYTES TO COPY
- MOV CX,AX ;MOVE INTO COUNTER
- MOV AX,0A000H
- MOV DS,AX ;GET THE SEGMENT FOR THE SOURCE
- ZIP:
- REP MOVSB ;COPY THAT SECTION OF SCREEN
-
- MOV CH,0 ;THE NUMBER OF LINES COPIED SO FAR
- MOV CL,00 ;THE NUMBER OF PIXELS
- TOP1:
- MOV SI,BX ;GET THE CORRECT OFFSET TO BE COPIED TO
- MOV AX,0A000H
- MOV ES,AX ;GET THE SEGMENT TO BE COPIED TO
- TOP2:
- MOV ES:[SI],CL ;COPY ACROSS THE SCREEN INCREMENTING VALUES
- INC SI ;MOVE TO NEXT PIXEL
- INC CL ;INCREMENT COUNTER
- JNE TOP2 ;IF COUNTER NOT EQUAL TO ZERO THEN COPY AGAIN
-
- ADD BX,320 ;MOVE DOWN TO NEXT LINE
- INC CH ;INCREMENT THE LINE COUNTER
- CMP CH,8 ;CHECK IF ALL THE LINES ARE DONE
- JNE TOP1 ;IF LINE COUNT <8 THEN COPY ANOTHER LINE
-
- POP ES
- POP DS
- POP BP
- RET
- SHOWPALV ENDP
-
- ;
- ; nopalv(&palstore,pal_xoff,pal_yoff);
- ;
- NOPALV PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,[BP+X] ;GET OFFSET OF ARRAY
- MOV SI,AX
- MOV AX,[BP+X+2] ;GET SEGMENT OF STORAGE ARRAY
- MOV DS,AX
-
- MOV AX,[BP+X+6] ;GET LINE TO COPY SCREEN BACK ONTO
- MOV DX,320 ;GET THE LINE LENGTH
- MUL DX ;GET THE OFFSET INTO THE SCREEN
- ADD AX,[BP+X+4] ;ADD IN THE X OFFSET
- JNC NO_ROLL2 ;ADDITION DIDN'T CARRY
- INC DX ;INCREMENT THE DX REGISTER ON A CARRY
- NO_ROLL2:
- MOV DI,AX ;KEEP TRACK OF THE OFFSET
- MOV AX,320 ;GET THE LINE LENGTH
- MOV DX,8 ;GET THE NUMBER OF LINES
- MUL DX ;GET THE NUMBER OF BYTES TO COPY
- MOV CX,AX ;MOVE INTO COUNTER
- MOV AX,0A000H
- MOV ES,AX ;GET THE SEGMENT FOR THE SOURCE
- ZOOM:
- REP MOVSB ;COPY THAT SECTION OF SCREEN
-
- POP ES
- POP DS
- POP BP
- RET
- NOPALV ENDP
-
- SCRLRITE PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,0A000H ;GET SEGMENT OF DISPLAY AREA
- MOV ES,AX ;USE THAT SEGMENT FOR BOTH DEST
- MOV DS,AX ;AND SOURCE
- MOV SI,63999 ;BEGINNING OF THE SOURCE TO MOVE
- MOV DI,64000 ;BEGINNING OF THE DEST
- MOV CX,63999 ;MOV THE ENTIRE SCREEN
- RITELOOP:
- MOVSB ;MOVE A BYTE
- DEC SI
- DEC SI
- DEC DI
- DEC DI
- LOOP RITELOOP ;GO BACK AND DO IT AGAIN
-
- POP ES
- POP DS
- POP BP
- RET
- SCRLRITE ENDP
-
-
- SCRLLEFT PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,0A000H ;SEGMENT OF DISPLAY AREA
- MOV ES,AX ;USE DISPLAY AREA FOR MOVE
- MOV DS,AX ;BOTH AS SOURCE AND DESTINATION
- MOV SI,1 ;START IN THE FIRST POSISTION TO MOVE FROM
- MOV DI,0 ;MOVE BACK TO THE PREVIOUS POSITION
- MOV CX,63999 ;MOVE THE WHOLE SCREEN
- ZOWIE:
- REP MOVSB ;ACTUALLY MOVE THE SCREEN
-
- POP ES
- POP DS
- POP BP
- RET
- SCRLLEFT ENDP
-
- SCRLUP PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,0A000H ;SEGMENT OF DISPLAY AREA
- MOV ES,AX ;USE DISPLAY AREA FOR MOVE
- MOV DS,AX ;BOTH AS SOURCE AND DESTINATION
- MOV SI,320 ;START IN THE FIRST POSISTION TO MOVE FROM
- MOV DI,0 ;MOVE BACK TO THE PREVIOUS POSITION
- MOV CX,63680 ;MOVE THE WHOLE SCREEN
- WHAM:
- REP MOVSB ;ACTUALLY MOVE THE SCREEN
-
- POP ES
- POP DS
- POP BP
- RET
- SCRLUP ENDP
-
- SCRLDOWN PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,0A000H ;GET SEGMENT OF DISPLAY AREA
- MOV ES,AX ;USE THAT SEGMENT FOR BOTH DEST
- MOV DS,AX ;AND SOURCE
- MOV SI,63680 ;BEGINNING OF THE SOURCE TO MOVE
- MOV DI,64000 ;BEGINNING OF THE DEST
- MOV CX,63680 ;MOV THE ENTIRE SCREEN
- DOWNLOOP:
- MOVSB ;MOVE A BYTE
- DEC SI
- DEC SI
- DEC DI
- DEC DI
- LOOP DOWNLOOP ;GO BACK AND DO IT AGAIN
-
- POP ES
- POP DS
- POP BP
- RET
- SCRLDOWN ENDP
- ;
- ; Invert A BOX ON THE SCREEN
- ;
- ; usage : outlinev(x1,y1,x2,y2)
- ;
- OUTLINEV PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,[BP+X+2] ; GET FIRST Y VALUE
- CMP AX,[BP+X+6] ; COMPARE WITH THE SECOND Y - VALUE
- JLE CHECKX ; OK ORDER GOTO CHECKING THE X VALUES
- MOV CX,AX ; SWAP THE TWO VALUES
- MOV AX,[BP+X+6] ;
- MOV [BP+X+2],AX ;
- MOV AX,CX ;
- MOV [BP+X+6],AX ;
- CHECKX:
- MOV AX,[BP+X] ; GET FIRST X VALUE
- CMP AX,[BP+X+4] ; COMPARE WITH THE SECOND X - VALUE
- JLE MAKELEN ; OK ORDER GOTO COMPUTING THE LENGTHS
- MOV CX,AX ; SWAP THE TWO VALUES
- MOV AX,[BP+X+4] ;
- MOV [BP+X],AX ;
- MOV AX,CX ;
- MOV [BP+X+4],AX ;
- MAKELEN: ; COMPUTE THE X AND Y WIDTHS FOR THE BOX TO BE INVERTED
- MOV AX,[BP+X+4] ; GET THE LARGER OF THE TWO X VALUES
- SUB AX,[BP+X] ; SUBTRACT THE SMALLER VALUE TO FIND THE LENGTH
- ADD AX,1 ;
- MOV [BP+X+4],AX ; STORE IT IN THE OLD LOCATION FOR THE 2ND X VALUE
- MOV AX,[BP+X+6] ; GET THE LARGER OF THE TWO Y VALUES
- SUB AX,[BP+X+2] ; SUBTRACT THE SMALLER VALUE TO FIND THE LENGTH
- SUB AX,1 ; SUBTRACT TWO FOR THE TOP AND BOTTOM EDGES
- CMP AX,0 ; CHECK IF IT IS LESS THAN ZERO
- JG POSITIVE ; JUMP AROUND ZEROING THE ACC.
- MOV AX,0
- POSITIVE:
- MOV [BP+X+6],AX ; STORE IT IN THE OLD LOCATION FOR THE 2ND Y VALUE
- MOV AX,320 ; COMPUTE THE VALUE TO ADD TO THE DI FOR COMPLETE WRAPAROUND
- SUB AX,[BP+X+4] ;
- MOV SI,AX ; KEEP TRACK OF IT
-
- MOV AX,0A000H ; DATA BUFFER
- MOV ES,AX
- ;
- MOV AX,[BP+X+2] ; GET Y VALUE AGAIN
- MOV DX,320 ; GET LENGTH OF A LINE
- MUL DX
- JA DONTFIXA ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
- MOV BX,ES ; GET THE ES
- ADD BX,DX ; INCREMENT THE ES
- MOV ES,BX ; AND REPLACE IT
- DONTFIXA:
- ADD AX,[BP+X] ; X VALUE OF WHERE ON SCREEN ADDED IN
- MOV DI,AX ; PREPARE FOR MOVS
- MOV CX,[BP+X+4] ; HOW MANY BYTES?
- BLASTA:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT THE VALUE THERE
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; INCREMENT TO NEXT POSITION
- LOOP BLASTA ; LOOP UNTIL ALL HAVE BEEN DONE
-
- ADD DI,SI ; MOVE OVER TO THE BEGINNING OF THE NEXT LINE
- MOV CX,[BP+X+6] ; COUNT VALUE FOR THE NEXT SERIES
- CMP CX,0 ; CHECK FOR NO LINES IN BETWEEN
- JLE BLAST2A ; JUMP AROUND PUTTING THE LINES IN BETWEEN
- BLAST2:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE INVERTED VALUE
- ADD DI,[BP+X+4] ; GO TO THE LAST VALUE TO INVERT ON THAT LINE
- SUB DI,1 ;
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE INVERTED VALUE
- ADD DI,SI ; GET THE VALUE FOR THE BEGINNING OF THE NEXT LINE
- INC DI ;
- LOOP BLAST2 ; DO THE NEXT LINE
-
- BLAST2A:
- MOV CX,[BP+X+4] ; PREPARE FOR LAST LINE
- BLAST3:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT THE VALUE THERE
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; INCREMENT TO NEXT POSITION
- LOOP BLAST3 ; LOOP UNTIL ALL HAVE BEEN DONE
-
- POP ES
- POP DS
- POP BP
- RET
- OUTLINEV ENDP
- ;
- ; Draw a 4x4 ball on the vga screen
- ;
- ; usage : ball(x,y)
- ;
- BALL PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,0A000H ; DATA BUFFER
- MOV ES,AX
- ;
- MOV AX,[BP+X+2] ; GET Y VALUE
- MOV DX,320 ; GET LENGTH OF A LINE
- MUL DX
- JA DONTFIXB ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
- MOV BX,ES ; GET THE ES
- ADD BX,DX ; INCREMENT THE ES
- MOV ES,BX ; AND REPLACE IT
- DONTFIXB:
- ADD AX,[BP+X] ; X VALUE OF WHERE ON SCREEN ADDED IN
- MOV DI,AX ; PREPARE FOR MOVS
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; MOVE OVER ONE BYTE
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE VALUE
-
- ADD DI,318 ; MOVE TO THE NEXT LINE
- MOV CX,4 ; HOW MANY BYTES?
- BLASTB:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT THE VALUE THERE
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; INCREMENT TO NEXT POSITION
- LOOP BLASTB ; LOOP UNTIL ALL HAVE BEEN DONE
-
- MOV CX,4 ; COUNT VALUE FOR THE NEXT SERIES
- ADD DI,316 ; MOVE OVER TO THE BEGINNING OF THE NEXT LINE
- BLASTC:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE INVERTED VALUE
- INC DI ;
- LOOP BLASTC ; DO THE NEXT LINE
-
- ADD DI,317 ; MOVE ONE BYTE OVER INTO THE NEXT LINE
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; MOVE OVER ONE BYTE
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE VALUE
-
- POP ES
- POP DS
- POP BP
- RET
- BALL ENDP
-
- ENDPS
- END